package Utilidades;

/**
 * @author Luis Antonio Lara Capetillo
 * Fecha: 24/07/11
 * Modificado: 20/01/12
 * 
 * Descripcion: clase encargada de la utilizacion de archivos
 * @version 3.0
 */

import java.io.*;
import java.util.StringTokenizer;

public class Archivo {

    private File archivo = null;
    private FileReader leer_Archivo = null;
    private BufferedReader leer_Buffer = null;
    private String str_Contenido;
    private String str_NomArchivo;
    private String str_Error;
    private String str_Linea[];
    private String str_LineaP1[];
    private String str_LineaP2[];
    private StringTokenizer sT_Alto;
    private LineaSeparada linea_Separada[];
    private int int_TotalLineas;

    public Archivo() {
        str_Contenido = "";
        str_Error = "";
        int_TotalLineas=0;
    }


    /*************************************************************************
     ***               Seccion de Setters y Getters                        ***
     *************************************************************************/

    /**
     * Metodo para pedir el nombre del archivo
     * @return direccion y nombre del archivo
     */
    public String getStr_NomArchivo() {
        return str_NomArchivo;
    }

    /**
     * Metodo para pedir el contenido del archivo completo
     * 
     * @return contenido del archivo
     */
    public String dameContenido() {
        return str_Contenido;
    }

    /**
     * Metodo para pedir el arreglo de lineas del archivo
     * @return str_Linea[]
     */
    public String[] getStr_Linea() {
        return str_Linea;
    }

    /**
     * Metodo para pedir la linea de un archivo
     * pasando como parametro el numero de la linea
     * deseada
     * 
     * @param numero de linea
     * @return
     */
    public String dameLinea(int num) {
        return str_Linea[num];
    }

    /**
     * Metodo para pedir la primera parte de la linea
     * pasando como parametros el numero de linea
     * 
     * @param num
     * @return 
     */
    public String dameLineaP1(int num) {
        return str_LineaP1[num];
    }

    /**
     * Metodo para pedir la segunda parte de la linea
     * pasando como parametros el nomero de linea
     * 
     * @param num
     * @return 
     */
    public String dameLineaP2(int num) {
        return str_LineaP2[num];
    }

    /**
     * Metodo para pedir el mensaje de error
     * @return 
     */
    public String dameError() {
        return str_Error;
    }

    /**
     * Metodo para obtener el arreglo de Linea_Separada
     *
     * @return linea_Separada[]
     */
    public LineaSeparada[] dameLinea_Separada() {
        return linea_Separada;
    }

    public int getInt_TotalLineas() {
        return int_TotalLineas;
    }


    /*************************************************************************
     ***               Seccion de Metodos                                  ***
     *************************************************************************/
    
    /**
     * Metodo para crear una carpeta con varios archivos dentro de la misma
     * 
     * @param str_NomCarpeta
     * @param str_NomArchivos 
     */
    public void m_CrearCarpeta_Archivos(String str_NomCarpeta, String[] str_NomArchivos, String str_Extencion){
        m_CrearCarpeta(str_NomCarpeta);
        for(int i=0;i<str_NomArchivos.length;i++){
            m_CrearArchivo(str_NomCarpeta+"/"+str_NomArchivos[i]+"."+str_Extencion);
        }
    }
    
    /**
     * Metodo encargado de la lectura de un archivo
     * y lo guarda todo en un String, tambien cuenta las lineas
     * de un archivo
     * 
     * @param nom_Archivo 
     */
    public void m_LeerArchivo(String nom_Archivo) {
        String str_linea;
        int_TotalLineas=0;
        str_Contenido="";
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                int_TotalLineas++;
                str_linea = leer_Buffer.readLine();
                str_Contenido += (str_linea + "\n");
            }
        } catch (Exception e) {
            str_Error="Error al leer el archivo: " + nom_Archivo + " ;" + e + "\n";
        } finally {
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo: " + e2 + "\n";
            }
        }
    }

    /**
     * Metodo para leer un archivo linea por linea y lo guarda en un arreglo
     * de lineas, tambien cuenta las lines del archivo
     *
     * @param nom_Archivo
     * @param num_Lineas
     */
    public void m_LeerLineas(String nom_Archivo, int num_Lineas) {
        str_Linea = new String[num_Lineas];
        int_TotalLineas=0;
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                str_Linea[int_TotalLineas] = leer_Buffer.readLine();
                str_Contenido += (str_Linea[int_TotalLineas] + "\n");
                int_TotalLineas++;
            }
        } catch (Exception e) {
            str_Error="Error en el metodo leerLineas(nom_Archivo,num_Lineas): " + e + "\n";
        } finally {    // En el finally cerramos el fichero
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo: " + e2 + "\n";
            }
        }
    }

    /**
     * Metodo para leer linea por linea de un archivo
     * y lo separa en 2 partes cada linea del archivo
     * separadas por un simbolo(token)
     * 
     * str_Linea es la linea completa
     * str_LineaP1 es la primera parte de la linea
     * str_LineaP2 es la segunda parte de la linea
     * 
     * @param nom_Archivo
     * @param num_Lineas
     * @param separador 
     */
    public void m_LeerLineas(String nom_Archivo, int num_Lineas, String separador) {
        str_Linea = new String[num_Lineas];
        str_LineaP1 = new String[num_Lineas];
        str_LineaP2 = new String[num_Lineas];
        int_TotalLineas=0;
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                str_Linea[int_TotalLineas] = leer_Buffer.readLine();
                sT_Alto = new StringTokenizer(str_Linea[int_TotalLineas], separador);
                str_LineaP1[int_TotalLineas] = sT_Alto.nextToken();
                str_LineaP2[int_TotalLineas] = sT_Alto.nextToken();
                int_TotalLineas++;
            }
        } catch (Exception e) {
            str_Error="Error en el metodo leerLineas(nom_Archivo,num_Linea,separador): " + e + "\n";
        } finally {    // En el finally cerramos el fichero
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo " +nom_Archivo+":"+ e2 + "\n";
            }
        }
    }

    /**
     * Metodo para leer linea por linea un archivo
     * y obtiner todos lo elementos(tokens) y los
     * coloca en una linea, es ideal para crear vectores
     * apartir de una matrix de datos
     * todo se guarda en la variable str_Contenido
     *
     * @param nom_Archivo
     * @param num_Elemento
     * @param separador
     */
    public void m_LeerMultiLineas(String nom_Archivo, int num_Elemento, String separador) {
        String linea = "";
        int_TotalLineas=0;
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                linea = leer_Buffer.readLine();
                sT_Alto = new StringTokenizer(linea, separador);
                for (int k = 0; k < num_Elemento; k++) {
                    String token = sT_Alto.nextToken();
                    str_Contenido = str_Contenido + token + "\n";
                }
                int_TotalLineas++;
            }
        } catch (Exception e) {
            str_Error="Error en el metodo leerMultiLineas: " + e + "\n";
        } finally {    // En el finally cerramos el fichero, para asegurarnos
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo: " + e2 + "\n";
            }
        }
    }

    /**
     * Metodo para leer un archivo el cual se obtienen las lineas separadas
     * en los numero de token asignados en el parametro de num_Elemento,
     * 
     * @param nom_Archivo  nombre de archivo
     * @param num_Elemento numero de token por linea
     * @param separador    simbolo de separador
     */
    public void m_LeerMultiTokens(String nom_Archivo, int num_Elemento, String separador) {
        String linea = "";
        m_LeerArchivo(nom_Archivo);
        linea_Separada= new LineaSeparada[int_TotalLineas];
        int num=0;
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                linea = leer_Buffer.readLine();
                sT_Alto = new StringTokenizer(linea, separador);
                linea_Separada[num]=new LineaSeparada(num_Elemento);
                for (int k = 0; k < num_Elemento; k++) {
                    String token = sT_Alto.nextToken();
                    linea_Separada[num].setStr_Palabras(k, token);
                }
                num++;
            }
        } catch (Exception e) {
            str_Error="Error en el metodo m_LeerMultiTokens: " + e + "\n";
        } finally {    // En el finally cerramos el fichero, para asegurarnos
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo: " + e2 + "\n";
            }
        }
    }

    /**
     * Metodo para leer un archivo el cual cada linea es dividida en tokens, loscuales
     * son guardados en un objeto LineaSeparada el cual es un arreglo de tipo String
     * en el cualse puede obtener la palabra decea de la linea.
     *
     * @param nom_Archivo
     * @param num_Elemento
     * @param separador
     */
    public void m_LeerMultiTokens(String nom_Archivo, int num_Elemento, String separador, int num_Lineas){
        linea_Separada= new LineaSeparada[num_Lineas];
        str_Linea =new String[num_Lineas];
        int_TotalLineas=0;
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                str_Linea[int_TotalLineas]=leer_Buffer.readLine();
                linea_Separada[int_TotalLineas]=new LineaSeparada(num_Elemento);
                sT_Alto = new StringTokenizer(str_Linea[int_TotalLineas], separador);
                
                for (int k = 0; k < num_Elemento; k++) {
                    String token = sT_Alto.nextToken();
                    linea_Separada[int_TotalLineas].setStr_Palabras(k, token); 
                }
                
                str_Contenido = str_Contenido + str_Linea+ "\n";
                int_TotalLineas++;
            }
        } catch (Exception e) {
            str_Error="Error en el metodo leerMultiTokens: " + e + "\n";
        } finally {    // En el finally cerramos el fichero, para asegurarnos
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo: " + e2 + "\n";
            }
        }
    }

    /**
     * Metodo encargado de la creacion un archivo
     * y lo guarda con el nombre pasado como parametro
     * 
     * @param nom_Archivo 
     */
    public void m_CrearArchivo(String nom_Archivo) {
        archivo = new File(nom_Archivo);
        try {
            if (archivo.createNewFile()) {
                str_Error="";
            } else {
                str_Error="El archivo ya existe: "+nom_Archivo;
            }
        } catch (IOException ioe) {
            str_Error="Error en el metodo m_CrearArchivo"+nom_Archivo+":"+ioe;
        }
    }

    /**
     * Metodo encargado de la sobrescritura de archivo
     * pasando como parametros el nombre del archivo
     * y un Sting con el contenido de la escritura
     * 
     * @param nom_Archivo
     * @param contenido 
     */
    public void m_SobreEscribir(String nom_Archivo, String contenido) {
        str_Error="";
        archivo = new File(nom_Archivo);
        try {
            if (archivo.exists()) {  // A partir del objeto File creamos el archivo fisicamente
                BufferedWriter bw = new BufferedWriter(new FileWriter(archivo));
                bw.write(contenido);
                bw.close();
            } else {
                str_Error="No se pudo sobre escribir en el archivo: " + nom_Archivo + "\n";
            }
        } catch (IOException ioe) {
            str_Error="Error inesperado: " + ioe;
        }
    }

    /**
     * Metodo para escribir en un archivo pasando como parametros el
     * (nombre del archivo, contenido del archivo)
     * 
     * @param nom_Archivo
     * @param contenido 
     */
    public void m_Escribir(String nom_Archivo, String contenido) {
        archivo = new File(nom_Archivo);
        try {
            if (archivo.exists()) {
                m_LeerArchivo(nom_Archivo);
                BufferedWriter bw = new BufferedWriter(new FileWriter(archivo));
                bw.write(str_Contenido + contenido);
                bw.close();
            } else {
                str_Error="No ha podido escribir en el archivo\n";
            }
        } catch (IOException ioe) {
            str_Error="Error inesperado: " + ioe;
        }
    }

    /**
     * Metodo para crear Carpeta con el nombre
     * pasado como parametro
     * 
     * @param nom_Carpeta 
     */
    public void m_CrearCarpeta(String nom_Carpeta) {
        File dir = new File(nom_Carpeta);
        dir.mkdirs();
    }

    /**
     * Metodo para leer un archivo con etiquetas de titulos,
     * guarda la informacion despues de cada titulo en una
     * variable str_Linea
     * @param nom_Archivo
     * @param str_Etiquetas 
     */
    public void m_LeerLineasConEtiquetas(String nom_Archivo, String[] str_Etiquetas) {
        String linea = "";
        str_Contenido="";
        int_TotalLineas=0;
        str_Linea= new String[str_Etiquetas.length];
        for (int i=0; i<str_Linea.length;i++){
            str_Linea[i]="";
        }
        int num=0;
        try {
            m_AsignarBuffer(nom_Archivo);
            while (leer_Buffer.ready()) {
                linea = leer_Buffer.readLine();
                if (linea.equals(str_Etiquetas[num])){
                    num++;
                }else{
                    str_Linea[num-1]+=""+linea+"\n";
                }
                str_Contenido+=""+linea+"\n";
                int_TotalLineas++;
            }
        } catch (Exception e) {
            str_Error="Error en el metodo m_LeerLineasConEtiquetas: " + e + "\n";
        } finally {    // En el finally cerramos el fichero, para asegurarnos
            try {
                if (null != leer_Archivo) {
                    leer_Archivo.close();
                }
            } catch (Exception e2) {
                str_Error="Error al cerrar el archivo: " + e2 + "\n";
            }
        }
    }

    private void m_AsignarBuffer(String nom_Archivo) throws Exception{
        System.out.println("Abrir archivo:"+nom_Archivo);
        try {
            InputStream is = getClass().getResourceAsStream("/" + nom_Archivo);
            leer_Buffer = new BufferedReader(new InputStreamReader(is));
        } catch (Exception e) {
            System.out.println("Exception: "+e.getMessage()+ "\t Abrir archivo externo");
            archivo = new File(nom_Archivo);
            leer_Archivo = new FileReader(archivo);
            leer_Buffer = new BufferedReader(leer_Archivo);
        }
    }

    public void m_ImprimeError() {
        System.out.println(dameError());
    }
}
